package edu.neusoft.yiqibike.service.impl;

import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import edu.neusoft.yiqibike.common.constant.GlobalConstant;
import edu.neusoft.yiqibike.common.entity.AdminRole;
import edu.neusoft.yiqibike.common.entity.RolePermission;
import edu.neusoft.yiqibike.common.entity.mysql.Admin;
import edu.neusoft.yiqibike.common.entity.mysql.Permission;
import edu.neusoft.yiqibike.common.entity.mysql.Role;
import edu.neusoft.yiqibike.common.exception.ArgumentVerifyException;
import edu.neusoft.yiqibike.common.exception.UserException;
import edu.neusoft.yiqibike.dao.mapper.AdminMapper;
import edu.neusoft.yiqibike.service.IAdminService;
import edu.neusoft.yiqibike.service.IAuthorizationService;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements IAdminService {
    private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();

    @Autowired
    private IAuthorizationService authorizationService;

    @Override
    public Page<Admin> getAdminList(Page<Admin> page) {
        Wrapper<Admin> wrapper = new EntityWrapper<>();
        if (Objects.nonNull(page) && !CollectionUtils.isEmpty(page.getCondition())) {
            String realname = (String) page.getCondition().get("realname");
            wrapper.like("realname", realname, SqlLike.RIGHT);
        }
        List<Admin> adminList = baseMapper.selectByPage(page, wrapper);
        if (!CollectionUtils.isEmpty(adminList)) {
            adminList = adminList.stream().sorted(Comparator.comparing(Admin::getCreateTime))
                    .collect(Collectors.toList());
            for (Admin admin : adminList) {
                if (Objects.nonNull(admin)) {
                    this.getAdminWithRoleAndPermission(admin);
                }
            }
        }
        page.setRecords(adminList);
        return page;
    }

    @Override
    public Admin getAdminById(Long aid) {
        return baseMapper.selectOneById(aid);
    }

    @Override
    public Admin getAdminByRealname(String realname) {
        return baseMapper.selectOneByRealname(realname);
    }

    @Override
    public void addAdmin(Admin admin) {
        //密码+盐
        admin.setSalt(randomNumberGenerator.nextBytes().toHex());
        String password = new SimpleHash(Md5Hash.ALGORITHM_NAME, admin.getPassword(), ByteSource.Util.bytes(admin.getSalt()),
                GlobalConstant.HASH_ITERATIONS).toHex();
        admin.setPassword(password);
        admin.insert();
    }

    @Override
    @Transactional
    public void invertIsEnable(Long aid, Integer isEnable) {
        if (1 == isEnable) {
            isEnable = -1;
        } else if (-1 == isEnable) {
            isEnable = 1;
        } else {
            throw new ArgumentVerifyException("【管理员可用状态】：非法");
        }
        baseMapper.invertIsEnable(aid, isEnable);
    }

    @Override
    public Admin getAdminWithRoleAndPermission(Admin admin) {
        List<Role> roles = authorizationService.getRolesByAid(admin.getId());
        List<String> role = roles.stream().map(Role::getCode).distinct().collect(Collectors.toList());
        admin.setRoles(role);
        Set<Long> rids = roles.stream().map(Role::getId).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(rids)) {
            List<Permission> permissions = authorizationService.getPermissionsByRids(rids);
            List<String> permission = permissions.stream().map(Permission::getCode).collect(Collectors.toList());
            admin.setPermissions(permission);
        }
        return admin;
    }

    @Override
    public List<Admin> getColleagueList(String departmentNo) {
        return new Admin().selectList(new EntityWrapper().eq("department", departmentNo));
    }

    @Override
    public void changePassword(String newPwd, String oldPwd, Admin loginAdmin) {
        loginAdmin = loginAdmin.selectById();
        String oldPassword = new SimpleHash(Md5Hash.ALGORITHM_NAME, oldPwd, ByteSource.Util.bytes(loginAdmin.getSalt()),
                GlobalConstant.HASH_ITERATIONS).toHex();
        if (!oldPassword.equals(loginAdmin.getPassword())) {
            throw new ArgumentVerifyException("原密码输入错误！");
        }
        loginAdmin.setSalt(randomNumberGenerator.nextBytes().toHex());
        String password = new SimpleHash(Md5Hash.ALGORITHM_NAME, newPwd, ByteSource.Util.bytes(loginAdmin.getSalt()),
                GlobalConstant.HASH_ITERATIONS).toHex();
        Admin admin = new Admin();
        admin.setId(loginAdmin.getId());
        admin.setPassword(password);
        admin.setSalt(loginAdmin.getSalt());
        admin.updateById();
    }
}
